package test1;

import org.apache.catalina.Context;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.startup.Tomcat;
import org.apache.coyote.http11.Http11Nio2Protocol;
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletRegistrationBean;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.AnnotationConfigWebApplicationContext;
import org.springframework.web.servlet.DispatcherServlet;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;

import javax.servlet.ServletContainerInitializer;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import java.io.File;
import java.nio.file.Files;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @author: mornd
 * @dateTime: 2023/5/10 - 23:47
 */
public class App {
    public static void main(String[] args) throws Exception {
        // 实例化对象
        Tomcat tomcat = new Tomcat();
        // 设置 tomcat 的工作空间
        tomcat.setBaseDir("tomcatWorkSpace");

        // 创建项目文件夹
        File docBase = Files.createTempDirectory("boot.tomcat.").toFile();
        // 虚拟机正常退出就主动删除该文件
        docBase.deleteOnExit();

        // 添加 context， 空字符串就代表/
        Context context = tomcat.addContext("", docBase.getAbsolutePath());

        // tomcat 整合 spring
        WebApplicationContext webApplicationContext = createWebApplicationContext();

        // 声明式添加 servlet
        context.addServletContainerInitializer((c, ctx) -> {
            // 添加自己的 servlet
            ctx.addServlet("myServlet", MyServlet.class).addMapping("/my");
            ctx.addFilter("myFilter", MyFilter.class);

            for (ServletRegistrationBean bean :
                    webApplicationContext.getBeansOfType(ServletRegistrationBean.class).values()) {
                bean.onStartup(ctx);
            }

        }, Collections.emptySet());

        // 启动
        tomcat.start();

        // 创建连接器
        Connector connector = new Connector(new Http11Nio2Protocol());
        connector.setPort(8080);
        tomcat.setConnector(connector);

    }

    public static WebApplicationContext createWebApplicationContext() {
        AnnotationConfigWebApplicationContext context = new AnnotationConfigWebApplicationContext();
        context.register(Config.class);
        context.refresh();
        return context;
    }

    @Configuration
    static class Config {

        @Bean //  这里需手动指定容器，否则会添加 XmlWebApplicationContext
        public DispatcherServlet dispatcherServlet(WebApplicationContext applicationContext) {
            return new DispatcherServlet(applicationContext);
        }

        @Bean
        public DispatcherServletRegistrationBean registrationBean(DispatcherServlet dispatcherServlet) {
            return new DispatcherServletRegistrationBean(dispatcherServlet, "/");
        }

        // 添加消息转换器
        @Bean
        public RequestMappingHandlerAdapter requestMappingHandlerAdapter() {
            RequestMappingHandlerAdapter handlerAdapter = new RequestMappingHandlerAdapter();
            handlerAdapter.setMessageConverters(Collections.singletonList(new MappingJackson2HttpMessageConverter()));
            return handlerAdapter;
        }

        @RestController
        static class Controller {

            @RequestMapping("get")
            public Map get() {
                return new HashMap() {{
                    put("k1", "v1");
                }};
            }
        }
    }
}
